# -*- coding: utf-8 -*-

__version__ = '0.0.1'
__author__  = '$zhangbo'
__time__    = '$2013-11-07 22:51:00'
__all__     = ['RedisCache']

from redis import Redis
from jpdog.config.redis import BaseRedisConfig

def with_redis_status(func):
    """装饰器，包装返回结果和Redis 状态
    """
    def inner(*args, **kwargs):
        error  = False
        result = None
        try:
            result = func(*args, **kwargs)
        except ConnectionError:
            error = True

        return {
                'result':  result,
                'error' :  error
               }
    
    return inner

class RedisBase(object):

    _Connection_ = None

    @with_redis_status
    def add_task(self, queue_id, md5):
        '''加入任务到不带优先级的任务队列'''
        return self._Connection_.lpush(queue_id, md5)

    @with_redis_status
    def get_task(self, queue_id):
        '''从任务队列中取任务'''
        return self._Connection_.rpop(queue_id)

    @with_redis_status
    def add_task_with_priority(self, queue_id, md5, priority):
        '''添加任务到Redis优先级队列中，priority值越大优先级越小'''
        return self._Connection_.zadd(queue_id, md5, priority)
    
    @with_redis_status
    def get_tasks_from_priority_queue(self, queue_id, max_count):
        '''从带优先级的队列中取出优先级最高的max_count个任务，如果max_count大于队列中任务个数，返回队列中任务个数'''
        return self._Connection_.zrevrange(queue_id, 0, max_count)

    @with_redis_status
    def get_one_task_from_priority_queue(self, queue_id):
        '''从带优先级的队列中取出优先级最高的max_count个任务，如果max_count大于队列中任务个数，返回队列中任务个数'''
        ret = self._Connection_.zrevrange(queue_id, 0, 0)
        if ret:
            return ret[0]
        return None

    @with_redis_status
    def rem_task_from_priority_queue(self, queue_id, md5):
        '''Notices:带优先级的任务队列从中取出任务后，任务并没有从队列中删除，需要根据任务取出状态自己调用删除'''
        return self._Connection_.zrem(queue_id, md5)

    def get_queue_len(self, queue_id):
        '''取得对应队列长度（普通队列）'''
        return int(self._Connection_.llen(queue_id))

    def is_connection_alive(self):
        '''检测Redis服务器状态，返回True为活跃，阻塞或者抛出异常为错误'''
        return self._Connection_.ping()

class RedisCache(RedisBase):
    '''Redis链接 Singleton'''

    _Connection_ = None

    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            cls._instance = super(RedisCache, cls).__new__(cls, *args, **kwargs)  
        return cls._instance

    def __init__(self):
        if not cls._Connection_:
            RedisCache._Connection_ = Redis( host = BaseRedisConfig.HOST,
                                             port = BaseRedisConfig.PORT,
                                             db   = BaseRedisConfig.DBID)
